﻿/**
 * @file XImageView.h
 * Copyright (c) Gaaagaa. All rights reserved.
 *
 * @author  : Gaaagaa
 * @date    : 2020-12-20
 * @version : 1.0.0.0
 * @brief   : 图片预览的视图部件。
 */

#include "XImageView.h"

#include <QPainter>
#include <QDesktopServices>
#include <QUrl>

////////////////////////////////////////////////////////////////////////////////

#include "xtypes.h"

/**********************************************************/
/**
 * @brief
 * 保持纵横比例（maintain aspect ratio）的情况下，
 * 依据限定的最大尺寸值（宽高），计算出缩放后的最大尺寸值（宽高），
 * 并将 居中 位置的矩形的水平与垂直 x, y 坐标计算出来。
 *
 * @note xut_mcx 和 xut_mcy 同时为 0 时，xut_rcx 和 xut_rcy 值不做修改。
 *
 * @param [out   ] xit_pox : 操作成功返回的 居中 矩形水平 x 坐标。
 * @param [out   ] xit_poy : 操作成功返回的 居中 矩形垂直 y 坐标。
 * @param [in,out] xit_rcx : 入参，原尺寸宽度；回参，操作成功返回的建议宽度。
 * @param [in,out] xit_rcy : 入参，原尺寸高度；回参，操作成功返回的建议高度。
 * @param [in    ] xit_mcx : 限定的最大尺寸宽度。为 0 时，以 xut_mcy 为准。
 * @param [in    ] xit_mcy : 限定的最大尺寸高度。为 0 时，以 xut_mcx 为准。
 *
 * @return x_bool_t
 *         - 成功，返回 X_TRUE；
 *         - 失败，返回 X_FALSE。
 */
static x_bool_t resize_to_center(
                    x_int32_t & xit_pox,
                    x_int32_t & xit_poy,
                    x_int32_t & xit_rcx,
                    x_int32_t & xit_rcy,
                    x_int32_t   xit_mcx,
                    x_int32_t   xit_mcy)
{
    x_float_t xft_mrx = 0.0F;
    x_float_t xft_mry = 0.0F;

    if ((xit_rcx <= 0) || (xit_rcy <= 0))
    {
        return X_FALSE;
    }

    if (0 != xit_mcx)
    {
        if (0 != xit_mcy)
        {
            xft_mrx = xit_mcx / (x_float_t)(xit_rcx);
            xft_mry = xit_mcy / (x_float_t)(xit_rcy);

            if ((xft_mrx - xft_mry) > 1e-6F)
            {
                xit_rcx = (x_int32_t)(xit_rcx * xft_mry);
                xit_rcy = xit_mcy;
                xit_pox = (xit_mcx - xit_rcx) / 2;
                xit_poy = 0;
            }
            else
            {
                xit_rcx = xit_mcx;
                xit_rcy = (x_int32_t)(xit_rcy * xft_mrx);
                xit_pox = 0;
                xit_poy = (xit_mcy - xit_rcy) / 2;
            }
        }
        else
        {
            xit_rcx = xit_mcx;
            xit_rcy = (x_int32_t)(xit_rcy * xit_mcx / (x_float_t)(xit_rcx));
            xit_pox = 0;
            xit_poy = (xit_mcy - xit_rcy) / 2;
        }
    }
    else
    {
        if (0 != xit_mcy)
        {
            xit_rcx = (x_int32_t)(xit_rcx * xit_mcy / (x_float_t)(xit_rcy));
            xit_rcy = xit_mcy;
            xit_pox = (xit_mcx - xit_rcx) / 2;
            xit_poy = 0;
        }
    }

    return X_TRUE;
}

////////////////////////////////////////////////////////////////////////////////
// XImageView

//====================================================================

//
// XImageView : constructor/destructor
//

XImageView::XImageView(QWidget *parent)
    : QWidget(parent)
{

}

XImageView::~XImageView(void)
{

}

//====================================================================

//
// XImageView : overrides
//

void XImageView::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    QRect hRect(0, 0, width(), height());
    painter.fillRect(hRect, QColor(128, 128, 128));

    if (!m_imgShow.isNull())
    {
        x_int32_t xit_pox = 0;
        x_int32_t xit_poy = 0;
        x_int32_t xit_rcx = m_imgShow.width();
        x_int32_t xit_rcy = m_imgShow.height();
        resize_to_center(xit_pox, xit_poy, xit_rcx, xit_rcy, width(), height());

        painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
        painter.drawImage(
                    QRect(xit_pox, xit_poy, xit_rcx, xit_rcy),
                    m_imgShow,
                    QRect(0, 0, m_imgShow.width(), m_imgShow.height()));
    }

    painter.setPen(Qt::black);
    painter.drawRect(hRect);
}

void XImageView::mouseDoubleClickEvent(QMouseEvent *event)
{
    QWidget::mouseDoubleClickEvent(event);

    if (!m_imgShow.isNull())
    {
        QDesktopServices::openUrl(QUrl::fromLocalFile(m_strPath));
    }
}

//====================================================================

//
// XImageView : public interfaces
//

/**********************************************************/
/**
 * @brief 设置当前显示的图片文件。
 */
bool XImageView::setCurrent(const QString & strFilePath)
{
    if (0 == m_strPath.compare(strFilePath, Qt::CaseInsensitive))
    {
        return true;
    }

    m_strPath = strFilePath;
    m_imgShow.load(strFilePath);

    update();

    return !m_imgShow.isNull();
}

